package nio.demo;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;

/**
 * @Desc:
 * @author: cww
 * @DateTime: 2020-02-04 17:14
 */

public class PathFileExample {
    /**
     * nio 中的 Path 和 File
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // Paths 的工厂方法生成绝对路径 Path
        Path path = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file\\nio\\nio-data.txt");
        // 通过 Files.exists 判断确认 path 对应的路径是否存在，第二个参数数组是评判路径是否存在时使用的规则
        // 数组包含LinkOption.NOFOLLOW_LINKS枚举类型，表示Files.exists不会跟进到路径中有连接的下层文件目录。
        // 表示path路径中如果有连接，Files.exists方法不会跟进到连接中去
        boolean exists = Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS});
        System.out.println("exists:" + exists);
        Path path1 = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file\\nio\\PathsFileExample.txt");
        Path newFile = null;
        try {
            newFile = Files.createFile(path1);
        } catch (IOException e) {
            System.out.println("File is already exists");
        }
        Path source = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file\\nio\\nio-data.txt");
        Path destinationPath = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file\\nio\\PathsFileExampleCopy.txt");
        // 从 source 复制一个新的 path 出来，如果目标已经存在则会抛出 FileAlreadyExistsException
        try {
            Files.copy(source, destinationPath);
        } catch (IOException e) {
            System.out.println("File is already exists");
        }
        // 如果复制的目标文件以及存在则覆盖
        Files.copy(source, destinationPath, StandardCopyOption.REPLACE_EXISTING);
        Path temp = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file\\nio\\temp\\PathsFileExample.txt");
        Path temp1 = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file\\nio\\temp\\PathsFileExampleCopy.txt");
        // 移动文件，若文件存在则覆盖
        Files.move(path1, temp, StandardCopyOption.REPLACE_EXISTING);
        Files.move(destinationPath, temp1, StandardCopyOption.REPLACE_EXISTING);
        Files.delete(temp1);
        Path dir = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file\\nio\\temp\\search");
//        Files.createDirectory(dir);
        // 创建相对路径 Path
        // 创建一个指向 c:.... 的文件夹实例
//        Path projects = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file","projects");
        // 创建一个指向 具体文件 nio-data.txt 的实例
//        Path file = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file", "projects\\nio\\nio-data.txt");
        // 使用相对路径时可以使用特殊符号 ".", ".."
        // "." 表示当前路径
//        Path currentDir = Paths.get(".");
        // ".."
//        Path parentDir = Paths.get("..");
//        System.out.println(currentDir.toAbsolutePath());

        // Path 的normalize()方法可以标准化路径。标准化的含义是路径中的.和..都被去掉，指向真正的路径目录地址
//        String originalPath =
//                "d:\\data\\projects\\a-project\\..\\another-project";

//        Path path1 = Paths.get(originalPath);
//        System.out.println("path1 = " + path1);
//
//        Path path2 = path1.normalize();
//        System.out.println("path2 = " + path2);
        // 输出结果如下
        // path1 = d:\data\projects\a-project\..\another-project
        // path2 = d:\data\projects\another-project
    }
}

/**
 * 文件夹搜索案例
 */
class SearchingForFiles {
    public static void main(String[] args) {
        Path rootPath = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file\\nio\\");
        String fileToFind = File.separator + "nio-data.txt";
        System.out.println("---------------------visitFile----------------------");
        try {
            // 遍历指定文件夹下所有子文件夹中符合名字的对应文件
            Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>(){
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    String fileString = file.toAbsolutePath().toString();
                    // 这里会打印每次遍历的文件名
//                    System.out.println("pathString: " + fileString);
                    if (fileString.endsWith(fileToFind)) {
                        System.out.println("file found at path : " + file.toAbsolutePath());
                        //也可以遍历删除满足条件的目标
//                    System.out.println("delete file: " + file.toString());
//                    Files.delete(file);
                    }


                    // 返回的枚举类型，决定了遍历文件夹下一步是做什么
                    // CONTINUE         下一步继续遍历
                    // TERMINATE        下一步立即停止
                    // SKIP_SIBLINGS    继续遍历，但是略去当前文件夹的同级文件夹，或当前文件的同级目录下的文件
                    // SKIP_SUBTREE     下一步继续遍历但是当前目录将不再进行遍历
                    //                  该返回仅对 preVisitDirectory() 方法起作用，
                    //                  如果是其他方法返回该参数则相当于返回 CONTINUE

                    return FileVisitResult.CONTINUE;
                }

                /**
                 * 当访问某个文件没有权限时，将调用该方法
                 * @param file
                 * @param exc
                 * @return
                 * @throws IOException
                 */
                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    String fileString = file.toAbsolutePath().toString();
                    System.out.println("you do not have the right permissions :" + fileString);
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("------------preVisitDirectory-------------------");
        try {
            // 遍历指定文件夹下的所有子文件夹
            Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>(){
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    String fileString = dir.toAbsolutePath().toString();
                    if (fileString.endsWith("search")) {
                        System.out.println("found the directory: " + fileString);
                    }
//                    System.out.println(fileString);
                    // 这里可以根据业务将服务条件的目录加入一个 list 便后续使用
                    return FileVisitResult.CONTINUE;
                }

                /**
                 * 在访问了一个文件夹后将调用该方法,通常用于打印日志，显示给控制台已经搜索了哪些文件夹
                 * @param dir
                 * @param exc
                 * @return
                 * @throws IOException
                 */
                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    String fileString = dir.toAbsolutePath().toString();
                    System.out.println(" visiting a directory: " + fileString);
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

class SearchFileTest {
    public static void main(String[] args) {
        Path searchRoot = Paths.get("C:\\Code\\spring-root\\src\\maindemo\\resources\\file");
        List<String> dirList = new ArrayList<>();
        List<String> fileList = new ArrayList<>();
        try {
            Files.walkFileTree(searchRoot, new SimpleFileVisitor<Path>(){
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    String dirFullName = dir.toAbsolutePath().toString();
                    if (dirFullName.contains("nio")) {
                        dirList.add(dirFullName);
                        System.out.println("found dir contains nio : " + dirFullName);
                    }
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    String fileDir = file.toAbsolutePath().toString();
                    Path fileNamePath = file.getFileName();
                    if (fileNamePath.toAbsolutePath().toString().contains("nio")) {
                        fileList.add(fileDir);
                        System.out.println("found file contains nio : " + fileDir);
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("files walk success");
        System.out.println("dirList: " + dirList.toString());
        System.out.println("fileList: " + fileList.toString());

    }
}